package sardine.route;

import sardine.HttpMethod;
import sardine.SardineBase;

import java.util.Objects;
import java.util.stream.IntStream;

/**
 * @auth bruce-sha
 * @date 2015/5/21
 */
class RouteEntry {

    final HttpMethod httpMethod;
    final String path;
    final String acceptedType;
    final Object target;

    //缓存
    final String[] pathSplits;

    public RouteEntry(HttpMethod httpMethod, String path, String acceptedType, Object target) {
        this.httpMethod = Objects.requireNonNull(httpMethod);
        this.path = Objects.requireNonNull(path);
        this.acceptedType = Objects.requireNonNull(acceptedType);
        this.target = Objects.requireNonNull(target);

        this.pathSplits = this.path.split("/");
    }

    boolean match(HttpMethod requestHttpMethod, String requestPath) {
        if ((HttpMethod.BEFORE == requestHttpMethod || HttpMethod.AFTER == requestHttpMethod)
                && (httpMethod == requestHttpMethod)
                && (SardineBase.ALL_PATHS.equals(path)))
            return true;

        if (httpMethod == requestHttpMethod) return isMatch(requestPath);
        else return false;
    }


    /**
     * 判断是否匹配
     * <p/>
     * 约束：两个长度必须相等，只有两个特殊情况
     * 特殊情况： /hello/* /hello/ 此时前者长1
     * 特殊情况： /hello/* /hello/bruce/sha 此时后者长n
     *
     * @param realPath
     * @return
     */
    private boolean isMatch(String realPath) {

        final String routePath = path;

        // 完全相等
        if (routePath.equals(realPath)) return true;

        // /结尾需要谨慎 /hello/应该匹配 /hello/*或者/hello/或者 /hello/:name 而不是/hello
        // 但是/hello/与/hello split出来是完全一样的{"","hello"}
        if (realPath.endsWith("/") && !(routePath.endsWith("/") || routePath.endsWith("*")))
//                || pathSplits[Math.max(pathSplits.length - 1, 0)].startsWith(":")))
            return false;

        final String[] routePathArray = routePath.split("/");
        final String[] realPathArray = realPath.split("/");

        int routePathLength = routePathArray.length;
        int realPathLength = realPathArray.length;

        //如果不等最后一位必须是*
        if (routePathLength != realPathLength) {
            if (!routePath.endsWith("*")) return false;
            if (routePathLength > realPathLength + 1) return false;
        }

        return !IntStream.range(0, Math.min(routePathLength, realPathLength))
                .parallel()
                .filter(i -> !routePathArray[i].startsWith(":"))
                .filter(i -> !routePathArray[i].equals("*"))
                .anyMatch(i -> !routePathArray[i].equals(realPathArray[i]));
    }
}